WKWebView,wkwebview加载HTML字符串

您所在的位置:网站首页 wkwebview 加载本地html WKWebView,wkwebview加载HTML字符串

WKWebView,wkwebview加载HTML字符串

2023-12-29 23:59| 来源: 网络整理| 查看: 265

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

wkwebview使用时需要导入(#import )

WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView。通过简单的测试即可发现UIWebView占用过多内存,且内存峰值更是夸张。WKWebView网页加载速度也有提升,但是并不像内存那样提升那么多。下面列举一些其它的优势:

更多的支持HTML5的特性官方宣称的高达60fps的滚动刷新率以及内置手势Safari相同的JavaScript引擎将UIWebViewDelegate与UIWebView拆分成了14类与3个协议(官方文档说明)另外用的比较多的,增加加载进度属性:estimatedProgress

常用属性:

@property (nonatomic, readonly) BOOL canGoBack; @property (nonatomic, readonly) BOOL canGoForward; - (WKNavigation *)goBack; - (WKNavigation *)goForward; - (WKNavigation *)reload; - (void)stopLoading; /* reloadFromOrigin会比较网络数据是否有变化,没有变化则使用缓存,否则从新请求。 goToBackForwardListItem:比向前向后更强大,可以跳转到某个指定历史页面 */ - (WKNavigation *)reloadFromOrigin; - (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; // 是否允许左右划手势导航,默认不允许 @property (nonatomic) BOOL allowsBackForwardNavigationGestures; // 加载进度 0 ~ 1 @property (nonatomic, readonly) double estimatedProgress; @property (nullable, nonatomic, readonly, copy) NSString *title; // 访问历史列表,可以通过前进后退按钮访问,或者通过goToBackForwardListItem函数跳到指定页面 @property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;

常用方法:

- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request; - (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL - (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL; - (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL #pragma mark - WKNavigationDelegate // 页面开始加载时调用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{ } // 当内容开始返回时调用 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{ } // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ } // 页面加载失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{ } // 接收到服务器跳转请求之后调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{ } // 在收到响应后,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ NSLog(@"%@",navigationResponse.response.URL.absoluteString); //允许跳转 decisionHandler(WKNavigationResponsePolicyAllow); //不允许跳转 //decisionHandler(WKNavigationResponsePolicyCancel); } // 在发送请求之前,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ NSLog(@"%@",navigationAction.request.URL.absoluteString); //允许跳转 decisionHandler(WKNavigationActionPolicyAllow); //不允许跳转 //decisionHandler(WKNavigationActionPolicyCancel); } #pragma mark - WKUIDelegate // 创建一个新的WebView - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{ return [[WKWebView alloc]init]; } // 输入框 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{ completionHandler(@"http"); } // 确认框 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{ completionHandler(YES); } // 警告框 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{ NSLog(@"%@",message); completionHandler(); }  网页加载进度监听: // 注册观察者 [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; // 监听网页加载进度 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ [self.progressView setProgress:self.webView.estimatedProgress animated:YES]; if (self.progressView.progress == 1) { self.progressView.hidden = YES; } } // 开始加载 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{ self.progressView.hidden = NO; } // 加载完成 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ self.progressView.hidden = YES; } // 加载失败 - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{ self.progressView.hidden = YES; } js调动oc 首先需要添加WKScriptMessageHandler协议 // 为了避免循环引用,在viewWillAppear中添加js事件,在viewDidDisappear中移除 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // 配置js环境 WKUserContentController *userCC = self.webView.configuration.userContentController; // 添加js事件 [userCC addScriptMessageHandler:self name:@"onClickName"]; } // 处理js交互 // 前端必须使用window.webkissageHandlers.注册的方法名.postMessage({body:传输的数据} /* 示例 window.webkissageHandlers.uploadRebate.postMessage({platName:data.platName,platId:data.platId,name:data.name,id:data.id}) 前端给的方法名为uploadRebate,给的参数是一个字典 */ - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"拦截的方法名%@ , 拦截的方法传过来的参数%@", message.name, message.body); } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated];{ // 移除js [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"onClickName"]; } oc调用js // 加载完成 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ //say()是JS方法名,completionHandler是异步回调block [self.webView evaluateJavaScript:@"say()" completionHandler:^(id _Nullable result, NSError * _Nullable error) { NSLog(@"%@",result); }]; } 清除缓存 // 清除缓存 +(void)deleteWebCache{ if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) { /* 在磁盘缓存上。 WKWebsiteDataTypeDiskCache, html离线Web应用程序缓存。 WKWebsiteDataTypeOfflineWebApplicationCache, 内存缓存。 WKWebsiteDataTypeMemoryCache, 本地存储。 WKWebsiteDataTypeLocalStorage, Cookies WKWebsiteDataTypeCookies, 会话存储 WKWebsiteDataTypeSessionStorage, IndexedDB数据库。 WKWebsiteDataTypeIndexedDBDatabases, 查询数据库。 WKWebsiteDataTypeWebSQLDatabases */ NSArray * types=@[WKWebsiteDataTypeCookies,WKWebsiteDataTypeLocalStorage]; NSSet *websiteDataTypes= [NSSet setWithArray:types]; NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0]; [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{ }]; } else { // 清楚Library目录下的 Cookies文件夹与WebKit文件夹里面的内容 NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"]; NSError *errors; [[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors]; NSString *WebKit = [libraryPath stringByAppendingString:@"/WebKit"]; NSError *error; [[NSFileManager defaultManager] removeItemAtPath:WebKit error:&error]; } } 页面导航逐级返回 if ([webV canGoBack]) { [webV goBack]; }else{ [self.navigationController popViewControllerAnimated:YES]; } 监听网页链接的变化

有时候监听跳转的代理不走,不知道为什么,只能用kvo先解决一下了

[_webViews addObserver:self forKeyPath:@"URL" options:NSKeyValueObservingOptionNew context:nil]; -(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context{ NSLog(@"url == %@",_webViews.URL.absoluteString); } 小知识,wkwebview播放背景音乐 WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; config.allowsInlineMediaPlayback = YES; config.mediaPlaybackRequiresUserAction = false; wkWebView=[[WKWebView alloc] initWithFrame:rect configuration:config]; wkWebView.UIDelegate=self; wkWebView.navigationDelegate=self;

 

wkwebview加载HTML字符串 - (void)setWKWeb{ //js脚本 (脚本注入设置网页样式) NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"; //注入 WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; WKUserContentController *wkUController = [[WKUserContentController alloc] init]; [wkUController addUserScript:wkUScript]; //配置对象 WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init]; wkWebConfig.userContentController = wkUController; //改变初始化方法 (这里一定要给个初始宽度,要不算的高度不对) WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, BKSCREEN_WIDTH - 30, 0) configuration:wkWebConfig]; webView.scrollView.bounces = NO; _wkWeb = webView; _wkWeb.navigationDelegate = self; } //网页加载完成 //页面加载完后获取高度,设置脚,注意,控制器里不能重写代理方法,否则这里会不执行 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ // document.body.scrollHeight(加载HTML源站用这个) document.body.offsetHeight;(加载HTML字符串) [webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id Result, NSError * error) { NSString *heightStr = [NSString stringWithFormat:@"%@",Result]; //必须加上一点 CGFloat height = heightStr.floatValue+15.00; //网页加载完成 NSLog(@"新闻加载完成网页高度:%f",height); self.wkWebHeigh = height; [self.tableV reloadData]; }]; }

补全网页代码,设置图片适应屏幕宽度(遍历网页中所有的图片,设置$img[p].style.width = '100%%')

NSString *htmlString = [NSString stringWithFormat:@" \n" " \n" " \n" "body {font-size:15px;}\n" " \n" " \n" "" "" "window.onload = function(){\n" "var $img = document.getElementsByTagName('img');\n" "for(var p in $img){\n" " $img[p].style.width = '100%%';\n" "$img[p].style.height ='auto'\n" " let height = document.body.offsetHeight;\n" "window.webkissageHandlers.imagLoaded.postMessage(height);\n" "}\n" "}" "%@" "" "", self.baseModel.desc]; BKLog(@"HTML字符串:%@", htmlString); [self.wkWeb loadHTMLString:htmlString baseURL:nil]; 计算高度方法二:(在 HTML DOM 中 Event 有个函数 onload 是用于一张页面或一幅图像完成加载时所执行的,我们需要监听所有的 img标签 或 body标签,然后在这个方法里发个消息给 WebKit 然后进行拦截)

" let height = document.body.offsetHeight;\n"   "window.webkissageHandlers.imagLoaded.postMessage(height);\n"

上面补全网页代码中这两行就是监听发送高度通知,然后我们只需要拦截imagLoaded这个js方法就可以拿到(document.body.offsetHeight)也就是网页的高度了

[self.wkWeb.configuration.userContentController addScriptMessageHandler:self name:@"imagLoaded"]; - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"拦截的方法名%@ , 拦截的方法传过来的参数%@", message.name, message.body); if ([message.name isEqualToString:@"imagLoaded"]) { CGFloat height = [message.body floatValue]; self.wkWebHeigh = height; [self.tableV reloadData]; } }

计算高度方法三:监听网页的加载状态(loading),比监听"scrollView.contentSize"属性调用的少

[self.wkWeb addObserver:self forKeyPath:@"loading" options:NSKeyValueObservingOptionNew context:nil]; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"loading"]) { [self.wkWeb evaluateJavaScript:@"document.body.scrollHeight" completionHandler:^(id Result, NSError * error) { NSString *heightStr = [NSString stringWithFormat:@"%@",Result]; //必须加上一点 CGFloat height = heightStr.floatValue; if (height == 0) { return ; } //网页加载完成 NSLog(@"新闻加载完成网页高度:%f",height); self.wkWebHeigh = height; [self.tableV reloadData]; }]; } }

 

 

 

 

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3